{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 单例设计模式\n",
    "# – 目的 —— 让 类 创建的对象，在系统中 只有 唯一的一个实例\n",
    "# – 每一次执行 类名() 返回的对象，内存地址是相同的"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "创建对象，分配空间\n",
      "播放器初始化\n",
      "<__main__.MusicPlayer object at 0x000002B6B97F7130>\n"
     ]
    }
   ],
   "source": [
    "# . __new__ 方法\n",
    "# • 使用 类名() 创建对象时，Python 的解释器 首先 会 调用 __new__ 方法为对象分配空间\n",
    "# • __new__ 是一个 由 object 基类提供的 内置的静态方法，主要作用有两个：\n",
    "# – 1) 在内存中为对象 分配空间\n",
    "# – 2) 返回 对象的引用\n",
    "# • Python 的解释器获得对象的 引用 后，将引用作为 第一个参数，传递给\n",
    "# __init__ 方法\n",
    "# 重写 __new__ 方法 的代码非常固定！\n",
    "# • 重写 __new__ 方法 一定要 return super().__new__(cls)\n",
    "# • 否则 Python 的解释器 得不到 分配了空间的 对象引用，就不会调用对象的初\n",
    "# 始化方法\n",
    "# • 注意：__new__ 是一个静态方法，在调用时需要 主动传递 cls 参数\n",
    "\n",
    "class MusicPlayer:\n",
    "    def __new__(cls, *args, **kwargs):\n",
    "        # 1. 创建对象时，new 方法会被自动调用\n",
    "        print(\"创建对象，分配空间\")\n",
    "        # 2. 为对象分配空间\n",
    "        instance = super().__new__(cls)\n",
    "        # 3. 返回对象的引用\n",
    "        return instance\n",
    "    def __init__(self):\n",
    "        print(\"播放器初始化\")\n",
    "\n",
    "# 创建播放器对象\n",
    "player = MusicPlayer()\n",
    "print(player)"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "播放器初始化\n",
      "<__main__.MusicPlayer object at 0x000002B6BA3C7AC0>\n",
      "<__main__.MusicPlayer object at 0x000002B6BA3C7AC0>\n",
      "播放周杰伦\n"
     ]
    }
   ],
   "source": [
    "# python中的单例\n",
    "# 单例 —— 让 类 创建的对象，在系统中 只有 唯一的一个实例\n",
    "# h) 定义一个 类属性，初始值是 None，用于记录 单例对象的引用\n",
    "# i) 重写 __new__ 方法\n",
    "# j) 如果 类属性 is None，调用父类方法分配空间，并在类属性中记录结果\n",
    "# k) 返回 类属性 中记录的 对象引用\n",
    "\n",
    "class MusicPlayer(object):\n",
    "    # 记录第一个被创建对象的引用\n",
    "    instance = None\n",
    "    # 记录是否执行过初始化动作\n",
    "    init_flag = False\n",
    "\n",
    "    @classmethod\n",
    "    def __new__(cls, *args, **kwargs):\n",
    "        if cls.instance is None:\n",
    "            # 2. 为对象分配空间\n",
    "            cls.instance = super().__new__(cls)\n",
    "            # 3. 返回对象的引用\n",
    "        return cls.instance\n",
    "\n",
    "    def __init__(self):\n",
    "        if not MusicPlayer.init_flag:\n",
    "            print(\"播放器初始化\")\n",
    "\n",
    "\n",
    "            MusicPlayer.init_flag = True\n",
    "\n",
    "    def play(self,music_name):\n",
    "        print(\"播放{}\".format(music_name))\n",
    "\n",
    "# 创建播放器对象\n",
    "player1 = MusicPlayer()\n",
    "print(player1)\n",
    "\n",
    "player2 = MusicPlayer()\n",
    "print(player2)\n",
    "\n",
    "player2.play(\"周杰伦\")\n",
    "\n",
    "# player1 和 player2 是同一个对象\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}